home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Archive / Graphics / QuickDraw GX / GX->PostScript Sample / GXToPostScript / Imaging Engine / SeperateUnderlineShape.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  10.2 KB  |  354 lines  |  [TEXT/MPS ]

  1. /*
  2.      File:        SeperateUnderlineShape.c
  3.  
  4.      Contains:    QuickDraw GX to PostScript conversion code.
  5.                          File contains routines to seperate text and glyph shapes that contain
  6.                         underlines in their text face into two shapes, one with just the text
  7.                         and the other with just the underline, converted into a path shape.
  8.  
  9.      Version:    Technology:    Quickdraw GX 1.1.x
  10.       
  11.      Copyright:    © 1992-1997 by Apple Computer, Inc., all rights reserved.
  12. */
  13.  
  14.  
  15. #include "GXToPSBuildConfig.h"
  16. #include <GXGraphics.h>
  17. #include "GXGraphicsPriv.h"
  18. #include <GXEnvironment.h>
  19. #include "GXToPostScript.h"
  20. #include "IOUtilities.h"
  21. #include "RDUtil.h"
  22. #include "FontHandler.h"
  23. #include "PublicPostScriptIE.h"
  24. #include "private.h"
  25. #include "PSIEResources.h"
  26. #include "GXErrors.h"
  27. #include "ShapeUtilities.h"
  28.  
  29. #ifdef resumeLabel
  30.     #undef resumeLabel
  31. #endif
  32. #define resumeLabel(exception)
  33.  
  34.  
  35. #ifdef DONTUSECHRISCODE
  36. //<FF>
  37. /*********************************************
  38.  
  39.     Function: SeperateUnderlineShape:
  40.  
  41.     Routine to generate two shapes from a text
  42.     or glyph shape.  One shape will be the original
  43.     shape, and the second one will be a copy of it
  44.     with only the underline layers in the text face…
  45.     This shape will be converted to a path.
  46.     
  47.     Any underline layers that are white layers will
  48.     be converted to paths and combined with the clip
  49.     of the source shape.
  50.     
  51.     The provided shape will be converted to a 
  52.     picture which will contain both shapes.
  53.     
  54. *********************************************/
  55. OSErr _SeperateUnderlineShape(TIEGlobalsHdl hIEGlobals, gxShape theShape)
  56.     {
  57.         OSErr                    status, saveStatus;
  58.         gxShape                underlineShape;
  59.         long                    nStyles;                        // Number of styles in the glyph shape.
  60. #if 0
  61.         short                    shortNstyles;                // GetLayout likes shorts.
  62. #endif
  63.         Handle                hWorkSpace;                    // the workspace.
  64.         gxTextFace        *theFace;                        // Pointer to a text face.
  65.         gxFaceLayer        *theLayer;                    // Pointer to a layer.
  66.         long                    nLayers;                        // Numbe of layers in the style.
  67.         gxStyle                *theStyles;                    // array of styles for the shape.
  68.         short                    *theRuns;                        // The style runs (required for calling SetGlhyphs)
  69.         long                    nChars;                            // Number of characters (required for calling setGlyphs)
  70.         gxStyle                *newStyles;                    // array of new styles for the underline shape.
  71.         gxStyle                *pStyle;                        // Pointer into array of new styles.
  72.         gxStyle                aStyle;                            // a particular style from the shape.
  73.         gxStyle                aNewStyle;                    // a particular new style for the new shape.
  74.         gxShapeType        theType;
  75.         long                    i, j;
  76.         long                    faceSize;                        // size of the text face
  77.         
  78.         char                    faceData[ sizeof(gxTextFace) + sizeof(gxFaceLayer) ];
  79.         
  80.         gxTextFace        *noDrawFace;                // text face that will cause no drawing.
  81.         
  82.         noDrawFace = (gxTextFace*)faceData;
  83.     
  84.         theType = GXGetShapeType(theShape);
  85.         check( (theType == gxTextType) || (theType == gxGlyphType) || (theType == gxLayoutType));
  86.  
  87.         aStyle = GXGetShapeStyle(theShape);            // get the shape's main style, we may need it.
  88.         
  89.         underlineShape = GXCopyToShape(nil, theShape);
  90.  
  91.         noDrawFace->faceLayers = 1;
  92.         ResetMapping(&noDrawFace->advanceMapping);
  93.         noDrawFace->faceLayer[0].outlineFill = gxNoFill;
  94.         noDrawFace->faceLayer[0].flags = 0x0000;
  95.         noDrawFace->faceLayer[0].outlineStyle = nil;
  96.         noDrawFace->faceLayer[0].outlineTransform = nil;
  97.         noDrawFace->faceLayer[0].boldOutset.x = 0;
  98.         noDrawFace->faceLayer[0].boldOutset.y = 0;
  99.         
  100.  
  101.         if (theType == gxTextType) {
  102.         
  103.             nStyles = 1;
  104.             theStyles = &aStyle;
  105.             newStyles = &aNewStyle;
  106.             
  107.         } else {
  108.             
  109.             if (theType == gxGlyphType) {
  110.             
  111.                 GXGetGlyphs(theShape, &nChars, nil, nil, nil, nil, &nStyles, nil, nil);
  112.                 
  113.             } else {
  114. #if 0            
  115.                 GXGetLayout(theShape, nil, &shortNstyles, nil, nil, nil, nil, nil, nil, nil);
  116.                 nStyles = shortNstyles;
  117. #else
  118.                 GXGetLayout(theShape, nil, &nStyles, nil, nil, nil, nil, nil, nil, nil);
  119. #endif                
  120.             }//end if
  121.             
  122.             /** Enough space for 2 of each style and the runs **/
  123.             
  124.             status = PSSetWorkSpaceSize(hIEGlobals, 2 * nStyles * sizeof(gxStyle) + nStyles * sizeof(short));
  125.             nrequire(status, failed_SrcStyleSpace);
  126.  
  127.             hWorkSpace = (*hIEGlobals)->hWorkSpace;            
  128.             HLock(hWorkSpace);
  129.             theRuns = (short*)*hWorkSpace;
  130.             theStyles = (gxStyle*)(*hWorkSpace + nStyles * sizeof(short));
  131.             newStyles = theStyles + nStyles;
  132.             
  133.             if (theType == gxGlyphType)
  134.                 GXGetGlyphs(theShape, nil, nil, nil, nil, nil, nil, theRuns, theStyles);
  135.             else
  136.                 GXGetLayout(theShape, nil, nil, theRuns, theStyles, nil, nil, nil, nil, nil);
  137.             
  138.         }//end if
  139.         
  140.         
  141.         /* Now loop through all styles, generate new ones with just underline layers */
  142.         pStyle = newStyles;        
  143.         for (i = 0; i < nStyles; i++) {
  144.         
  145.             if (*theStyles == nil)
  146.                 *theStyles = aStyle;
  147.                 
  148.             *pStyle = GXCopyToStyle(nil, *theStyles);            // make a copy of the style.
  149.         
  150.             nLayers = GXGetStyleFace(*theStyles, nil);
  151.             
  152.             if (nLayers >= 0) {            // as long as there was a face, even with no layers…
  153.                 
  154.                 faceSize = sizeof(gxTextFace) + nLayers * sizeof(gxFaceLayer);            
  155.                 nrequire(status = PSSetWorkSpaceSize(hIEGlobals, faceSize), failed_FaceSpace);
  156.                     
  157.                 theFace = (gxTextFace*)(*(*hIEGlobals)->hWorkSpace);        // Hope gx graphics calls don't move memory.
  158.                 
  159.                 GXGetStyleFace(*theStyles, theFace);
  160.                 
  161.  
  162.                 /** Make a new text face that has all of the non-underline layers set to noFill **/
  163.     
  164.                 if (nLayers > 0) {
  165.                         
  166.                     theLayer = theFace->faceLayer;
  167.                                     
  168.                     for (j = nLayers - 1; j >= 0; --j) {
  169.                     
  170.                         /******
  171.                             Leave glyph clip layers with their original fill, necessary for converting 
  172.                                 underline to a path, so underline gets clipped to glyphs.
  173.                         ******/
  174.                         if (!(theLayer->flags & kUnderlineCheckMask) || !(theLayer->flags & gxClipLayer))
  175.                             theLayer->outlineFill = gxNoFill;
  176.                                                                 
  177.                         ++theLayer;
  178.                     
  179.                     }//end for
  180.                                     
  181.                     
  182.                 } else if (nLayers == 0) {                // Make a non drawing layer.
  183.                         
  184.                         /**
  185.                             We know we have enough workspace for at least one layer since this block is
  186.                                 only executed if nLayers > 0, so construct a no drawing layer and the
  187.                                 sizeof(gxTextFace) has room for at least one layer because of anyNumber constant.
  188.                         ***/
  189.                         theFace->faceLayers = 1;
  190.                         theFace->faceLayer[0].outlineFill = gxNoFill;
  191.                         theFace->faceLayer[0].outlineStyle = nil;
  192.                         theFace->faceLayer[0].outlineTransform = nil;
  193.                         theFace->faceLayer[0].flags = 0;
  194.                         theFace->faceLayer[0].boldOutset.x = 0;
  195.                         theFace->faceLayer[0].boldOutset.y = 0;
  196.                     
  197.                     }//end if
  198.                 
  199.                     GXSetStyleFace(*pStyle, theFace);
  200.             
  201.             } else {            // the style had no face, do something to make it not draw.
  202.                 
  203.                 GXSetStyleFace(*pStyle, noDrawFace);
  204.  
  205.             }//end if
  206.  
  207.             if (nLayers >= 0) {            //if we allocated workspace for face, get rid of it.
  208.             
  209.                 /** First dispose of styles and transforms in the face **/
  210.                 theLayer = theFace->faceLayer;
  211.                 for (j = 0; j < nLayers; ++j) {
  212.                 
  213.                     if (theLayer->outlineStyle != nil)
  214.                         GXDisposeStyle (theLayer->outlineStyle);
  215.                     
  216.                     if (theLayer->outlineTransform != nil)
  217.                         GXDisposeTransform(theLayer->outlineTransform);
  218.                     
  219.                     ++theLayer;
  220.                     
  221.                 }//end for
  222.             
  223.                 status = PSReleaseWorkSpace(hIEGlobals);                // release workspace for this style's face.
  224.                 nrequire(status, failed_FaceSpace);
  225.                 
  226.             }//end if
  227.             
  228.             ++theStyles;
  229.             ++pStyle;
  230.         
  231.         }//end for
  232.         
  233.         /** Now we have an array of new styles that contain only layers in the face that don't draw **/
  234.         
  235.         if (theType == gxTextType) {
  236.         
  237.             GXSetShapeStyle(underlineShape, aNewStyle);
  238.             GXDisposeStyle(aNewStyle);
  239.             
  240.         } else {                
  241.                 
  242.                 if (theType == gxGlyphType)
  243.                     GXSetGlyphs(underlineShape, nChars, nil, nil, nil, nil, theRuns, newStyles);
  244.                 else
  245.                     GXSetLayout(underlineShape, 0, nil, nil, nStyles, theRuns, newStyles, nil, nil, nil, nil, nil);
  246.                     
  247.                 pStyle = newStyles;
  248.                 for ( i = 0; i < nStyles; ++i)
  249.                     GXDisposeStyle(*pStyle++);
  250.         
  251.         }//end if
  252.  
  253.  
  254.         /** Now generate the 2 shape picture, one shape the original, 2nd is path version of underlines **/
  255.         
  256.         GXSetShapeType(underlineShape, gxPathType);
  257.  
  258. #if DEBUGLEVEL > 1
  259.         //GXMoveShape(underlineShape, ff(100), ff(100));            // So we can see shape by itself.
  260. #endif
  261.  
  262.         GXSetShapeType(theShape, gxPictureType);
  263.         GXSetPictureParts(theShape, 0, 0, 1, &underlineShape, nil, nil, nil);
  264.         
  265.         status = GXGetGraphicsError(nil);
  266.         ncheck(status);
  267.         
  268. failed_FaceSpace:
  269.  
  270.         saveStatus = PSReleaseWorkSpace(hIEGlobals);                // release workspace used for source styles.
  271.         if (status == noErr) 
  272.             status = saveStatus;
  273.  
  274. failed_SrcStyleSpace:
  275.  
  276.         return(status);
  277.         
  278.     }//SeperateUnderlineShape
  279.  
  280. #else
  281.  
  282.  
  283. /*********************************************
  284.  
  285.     Function: SeperateUnderlineShape:
  286.  
  287.     Routine to generate two shapes from a text
  288.     layout, or glyph shape.  One shape will be the original
  289.     shape, and the second one will be a picture
  290.     containing the underlines.
  291.     
  292. *********************************************/
  293. OSErr _SeperateUnderlineShape(TIEGlobalsHdl hIEGlobals, gxShape theShape)
  294.     {
  295. #pragma unused(hIEGlobals)
  296.  
  297.         OSErr                    status = noErr;
  298.         gxShape                underlineShape;
  299.         gxShapeType        theType;
  300.         gxShape                shapeCopy;
  301.  
  302.         theType = GXGetShapeType(theShape);
  303.         if ( (theType == gxTextType) || (theType == gxGlyphType) || (theType == gxLayoutType) ) {
  304.  
  305.             /* Get the picture full of underline shapes */        
  306.     
  307.             if ( (theType == gxTextType) || (theType == gxGlyphType) ) {
  308.             
  309.                 underlineShape = GXGetGlyphUnderlines(theShape);
  310.                 
  311.             } else {
  312.             
  313.                 shapeCopy = GXCopyToShape(nil, theShape);
  314.                 nrequire(status = GXGetGraphicsError(nil), failed_copy);
  315.                 
  316.                 if (theType == gxLayoutType)
  317.                     GXPrimitiveShape(shapeCopy);                                // convert it to a glyph shape with layout applied.
  318.                 else
  319.                     GXSetShapeType(shapeCopy, gxGlyphType);            // was a text shape, make it a glyph shape.
  320.                 
  321.                 #if DEBUGLEVEL > 1
  322.                     theType = GXGetShapeType(shapeCopy);
  323.                     if (theType != gxGlyphType)
  324.                         dprintf(trace, "Fatal Error, primitiveShape did not make glyph from layout");
  325.                 #endif
  326.                 
  327.                 underlineShape = GXGetGlyphUnderlines(shapeCopy);
  328.                 GXDisposeShape(shapeCopy);
  329.             
  330.             }//end if
  331.  
  332.             /* Make the original shape a picture and add the underline shape to it. */
  333.             
  334.             GXSetShapeType(theShape, gxPictureType);
  335.             GXSetPictureParts(theShape, 0, 0, 1, &underlineShape, nil, nil, nil);
  336.             
  337.             #ifdef noBugs
  338.             GXDisposeShape(underlineShape);
  339.             #endif
  340.             
  341.             status = GXGetGraphicsError(nil);
  342.             ncheck(status);
  343.             
  344.         }//end if
  345.  
  346. failed_copy:
  347. failed_notText:
  348.  
  349.         return(status);
  350.  
  351.     }//SeperateUnderlineShape
  352.  
  353. #endif
  354.